import { cloneDeep } from 'lodash-es';
import type { RouteRecordRaw } from 'vue-router';
import router from '..';
import { basicRoute } from '../routes';
import { asyncRoutes } from '../routes/modules/index';
import { otherRoutes } from '../routes/other';

const transformMenuToRoutes = (
  routes: RouteRecordRaw[],
  menus: Global.Menus[],
): RouteRecordRaw[] => {
  function compareNodes(
    route: RouteRecordRaw,
    menu: Global.Menus,
  ): RouteRecordRaw | null {
    if (!route || !menu) return null;
    if (
      menu.name &&
      menu.name.toUpperCase() === (route.name as string).toUpperCase()
    ) {
      const _route: Omit<RouteRecordRaw, 'children'> & {
        children: RouteRecordRaw[];
      } = {
        ...route,
        meta: { ...route.meta },
        children: [],
      };

      const rChildren = route.children || [];
      const mChildren = menu.children || [];

      for (const route of rChildren) {
        for (const menu of mChildren) {
          const r = compareNodes(route, menu);
          if (r) {
            _route.children.push(r);
            _route.redirect = _route.children[0].path;
          }
        }
      }

      return _route as RouteRecordRaw;
    }

    return null;
  }

  const result: RouteRecordRaw[] = [];

  for (const menu of menus) {
    for (const route of routes) {
      const r = compareNodes(route, menu);
      if (r) {
        result.push(r);
      }
    }
  }

  return result;
};

const normalizeRoutes = (
  asyncRoutes: RouteRecordRaw[],
  parentRoute?: RouteRecordRaw,
): RouteRecordRaw[] => {
  const routes: RouteRecordRaw[] = [];

  for (const route of asyncRoutes) {
    const path = route.path.startsWith('/') ? route.path : `/${route.path}`;
    route.path = parentRoute ? parentRoute.path + path : path;
    if (route.children?.length) {
      const firstChildPath = route.children[0].path;
      const _firstChildPath = firstChildPath.startsWith('/')
        ? firstChildPath
        : `/${firstChildPath}`;
      route.redirect = route.path + _firstChildPath;
      route.children = normalizeRoutes(route.children, route);
    }
    routes.push(route);
  }

  return routes;
};

export const generateDynamicRoutes = (
  menus: Global.Menus[],
  isAdmin: boolean,
): RouteRecordRaw[] => {
  const routes = normalizeRoutes(cloneDeep(asyncRoutes));
  const authRouter = isAdmin
    ? routes
    : transformMenuToRoutes(routes, menus || []);
  const _routes = basicRoute.children
    ? [basicRoute.children[0], ...authRouter, ...otherRoutes]
    : [...authRouter, ...otherRoutes];
  basicRoute.children = _routes;
  router.addRoute(basicRoute);
  return basicRoute.children as RouteRecordRaw[];
};
